package com.apexsoft.monitor.common;

import com.apexsoft.front.common.db.mysql.ReflectObject;
import com.apexsoft.front.common.utils.BeanMethodUtil;
import com.apexsoft.front.common.utils.ClassMapping;
import com.apexsoft.front.common.utils.MysqlClassUtil;
import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.core.RowMapper;

import java.io.Reader;
import java.sql.Clob;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;

public class MysqlDaoSupportMapper implements RowMapper 
{
	private String classType;
	public MysqlDaoSupportMapper()
	{
		super();
		this.classType = ReflectObject.class.getName();
	}
	public MysqlDaoSupportMapper(String classType)
	{
		super();
		this.classType = classType;
	}
	public MysqlDaoSupportMapper(Class<?> cls)
	{
		super();
		this.classType = cls.getName();
	}
	
	public Object mapRow(ResultSet rs, int row) throws SQLException
	{
		Object o = getObjectInstance();
		ResultSetMetaData rsmd = rs.getMetaData();
		for(int i=1;i<=rsmd.getColumnCount();i++)
		{
			//获取属性相应的set方法
			String setMethod = BeanMethodUtil.getSetMethod(rsmd.getColumnLabel(i));
			//根据字段类型获取相关映射参数
			ClassMapping mapping = MysqlClassUtil.getColumnClassMapping(rsmd.getColumnTypeName(i));
			try
			{
				//都存放到map中
				o.getClass().getMethod(
						"setProperty",
						new Class[]{String.class,Object.class}
						).invoke(
								o, 
								new Object[]{rsmd.getColumnLabel(i).toLowerCase(),rs.getObject(rsmd.getColumnLabel(i))}
								);
				//如果存在相应的属性，保存字段值到bean属性
				if("CLOB".equals(rsmd.getColumnTypeName(i))) //处理CLOB
				{
					String clobStr = clob2String(rs.getClob(rsmd.getColumnLabel(i)));
					if(BeanMethodUtil.hasMethod(o, setMethod))
					{
						o.getClass().getMethod(
								setMethod,
								new Class[]{String.class}
								).invoke(
										o,
										new Object[]{clobStr}
										);
					}
				}
				else //其他所有
				{
					if(BeanMethodUtil.hasMethod(o, setMethod))
					{
						o.getClass().getMethod(
								setMethod,
								mapping.getClassType()
								).invoke(
										o,
										new Object[]{rs.getClass().getMethod(mapping.getTakeMethod(),new Class[]{String.class}).invoke(rs,new Object[]{rsmd.getColumnLabel(i)})}
										);
					}
				}
			}
			catch(Exception e)
			{
				//不做处理:bean中对应字段方法不存在的情况
				LogFactory.getLog(MysqlDaoSupportMapper.class).error(e.getMessage());
			}
		}
		return o;
	}
	//创建获取映射对象一个新的实例
	@SuppressWarnings("unchecked")
	private Object getObjectInstance()
	{
		try
		{
			Class c = Class.forName(classType);
			Object obj = c.getConstructor(new Class[]{}).newInstance(new Object[]{});
			return obj;
		}
		catch(Exception e)
		{
			LogFactory.getLog(MysqlDaoSupportMapper.class).error(e.getMessage());
			return new ReflectObject();
		}
	}
	
	/**
	 * clob 2 string
	 * @param clob
	 * @return
	 */
	private final String clob2String(Clob clob)
    {
      if (clob == null)
      {
        return null;
      }
      
      StringBuffer sb = new StringBuffer(65535);//64K
      Reader clobStream = null;//创建一个输入流对象
      try
      {
        clobStream = clob.getCharacterStream();
        char[] b = new char[60000];//每次获取60K
        int i = 0;
        while((i = clobStream.read(b)) != -1)
        {
          sb.append(b,0,i);
        }
      }
      catch(Exception ex)
      {
        sb = null;
      }
      finally
      {
        try
        {
          if (clobStream != null)
            clobStream.close();
        }
        catch (Exception e)
        {
        }
      }
      if (sb == null)
        return null;
      else
        return sb.toString();
    }

	
}
